package com.zzyl.serve.service.impl;

import java.time.LocalDateTime;
import java.time.Period;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.common.utils.StringUtils;
import com.zzyl.serve.domain.*;
import com.zzyl.serve.dto.*;
import com.zzyl.serve.mapper.*;
import com.zzyl.serve.util.CodeGenerator;
import com.zzyl.serve.vo.CheckInConfigVo;
import com.zzyl.serve.vo.CheckInDetailVo;
import com.zzyl.serve.vo.CheckInElderVo;
import com.zzyl.serve.vo.ElderFamilyVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zzyl.serve.service.ICheckInService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

/**
 * 入住Service业务层处理
 * 
 * @author liuyp
 * @date 2025-08-17
 */
@Service
public class CheckInServiceImpl extends ServiceImpl<CheckInMapper, CheckIn> implements ICheckInService
{
    @Autowired
    private CheckInMapper checkInMapper;
    @Autowired
    private ElderMapper elderMapper;
    @Autowired
    private BedMapper bedMapper;
    @Autowired
    private CheckInConfigMapper checkInConfigMapper;
    @Autowired
    private ContractMapper contractMapper;
    /**
    * 这里实现各个表的存储，处理参数中的四个dto
    * */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addCheckInApply(CheckInApplyDto checkInApplyDto) {
        //先进行逻辑判断？（老人是否已入住？）是的话就过，已入住了。否的话更新床位状态，然后开始更新老人数据新增老人、
        // (判断条件是老人表中有身份证存在且状态是1启用)
        LambdaQueryWrapper<Elder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Elder::getIdCardNo, checkInApplyDto.getCheckInElderDto().getIdCardNo());
        Elder elderDb = elderMapper.selectOne(queryWrapper);
        if (elderDb != null && elderDb.getStatus().equals(1)){
            throw new BaseException("老人已入住");
        }

        //未入住的情况，要更改床位状态
        Bed bed = bedMapper.selectBedById(checkInApplyDto.getCheckInConfigDto().getBedId());
        if (Objects.equals(bed.getBedStatus(),1)){
            throw new BaseException("床位已入住");
        }
        bed.setBedStatus(1);
        bedMapper.updateById(bed);

        //先存储老人基本信息(存在一个表中，我该是分开进行存储操作，还是全部转换成elder对象进行存储)
        CheckInElderDto checkInElderDto = checkInApplyDto.getCheckInElderDto();
        Elder elder = new Elder();
        BeanUtils.copyProperties(checkInElderDto,elder);
        //还需要补充状态、床id床编号、备注remark存放家属
        elder.setStatus(1);
        elder.setBedId(bed.getId());
        elder.setBedNumber(bed.getBedNumber());
        //家属信息是列表，要转换成字符串形式
        List<ElderFamilyDto> elderFamilyDtoList = checkInApplyDto.getElderFamilyDtoList();
        elder.setRemark(JSONUtil.toJsonStr(elderFamilyDtoList));
        if (elderDb == null){
            //如果刚才从数据库中查询的老人为null：要新增老人信息
            elderMapper.insertElder(elder);
        }else {
            //要更新老人信息
            elder.setId(elderDb.getId());
            elderMapper.updateById(elder);
        }

        //老人存储结束，存储其它信息
        //存储入住信息
        CheckInConfigDto checkInConfigDto = checkInApplyDto.getCheckInConfigDto();
        CheckIn checkIn = new CheckIn();
        checkIn.setElderId(elder.getId());
        checkIn.setElderName(elder.getName());
        checkIn.setIdCardNo(elder.getIdCardNo());
        checkIn.setStartDate(checkInConfigDto.getStartDate());
        checkIn.setEndDate(checkInConfigDto.getEndDate());
        checkIn.setNursingLevelName(checkInConfigDto.getNursingLevelName());
        checkIn.setBedNumber(bed.getBedNumber());
        checkIn.setStatus(0);
        save(checkIn);

        //存储配置信息
        CheckInConfig config = new CheckInConfig();
        BeanUtils.copyProperties(checkInConfigDto,config);
        config.setCheckInId(checkIn.getId());
        checkInConfigMapper.insert(config);

        //存储合同信息
        Contract contract = new Contract();
        CheckInContractDto checkInContractDto = checkInApplyDto.getCheckInContractDto();
        BeanUtils.copyProperties(checkInContractDto,contract);
        contract.setElderId(elder.getId());
        contract.setElderName(elder.getName());
        contract.setContractNumber("HT" + CodeGenerator.generateContractNumber());
        contract.setStartDate(checkInConfigDto.getStartDate());
        contract.setEndDate(checkInConfigDto.getEndDate());
        //  如果当前时间 不早于合同开始时间，且不晚于合同结束时间，说明在合同有效期内
        LocalDateTime now = LocalDateTime.now();
        boolean beInForce = !now.isBefore(contract.getStartDate()) && !now.isAfter(contract.getEndDate());
        contract.setStatus(beInForce?1:0);
        contractMapper.insert(contract);

    }

    /**
     * 查询入住
     * 查询入住信息，也就是从四个表中取出对应的数据，然后转换成vo类型
     * 老人表设计的没有年龄这个字段，存储是没有成功的。所以查询回显的时候是通过身份证来确定年龄？
     * @param id 入住表checkin的查询的老人的id
     * @return 入住
     */
    @Override
    public CheckInDetailVo selectCheckInById(Long id)
    {
        //我需要的是老人的id，不是入住表的老人所在的入住id，要获取入住表的老人的老人id，需要对参数的入住id进行处理
        CheckIn checkIn = checkInMapper.selectCheckInById(id);
        Elder elder = elderMapper.selectElderById(checkIn.getElderId());
        //增加空值判断
        if (elder == null){
            throw new BaseException("未找到对应的老人信息");
        }
        //将老人这个elder对象的值转换成CheckInElderVo
        CheckInElderVo checkInElderVo = new CheckInElderVo();
        BeanUtils.copyProperties(elder,checkInElderVo);

        //配置信息（好像不能这样取）这样的参数id是配置表的id而他们的联系是入住表id
        CheckInConfig config = checkInConfigMapper.selectCheckInConfigById(id);
        CheckInConfigVo checkInConfigVo = new CheckInConfigVo();
        // 添加空值检查
        if (config != null) {
            BeanUtils.copyProperties(config, checkInConfigVo);
        }
        //合同信息
        Contract contract = contractMapper.selectContractById(checkIn.getElderId());
        //将家属放进去(家属是以列表转成字符串的形式存放在老人表的remark中)
        //转换家属列表--字符串怎么转？
        List<ElderFamilyVo> elderFamilyVoList = new ArrayList<>();
        String remark = elder.getRemark();
        if (StringUtils.isNotEmpty(remark)){
            List<ElderFamilyDto> elderFamilyDtoList = JSONUtil.toList(remark, ElderFamilyDto.class);
            for (ElderFamilyDto dto : elderFamilyDtoList) {
                ElderFamilyVo vo = new ElderFamilyVo();
                BeanUtils.copyProperties(dto,vo);
                elderFamilyVoList.add(vo);
            }
        }
        else {
            elderFamilyVoList = null;
        }
        //整合数据
        CheckInDetailVo checkInDetailVo = new CheckInDetailVo();
        checkInDetailVo.setCheckInConfigVo(checkInConfigVo);
        checkInDetailVo.setContract(contract);
        checkInDetailVo.setElderFamilyVoList(elderFamilyVoList);
        checkInDetailVo.setCheckInElderVo(checkInElderVo);

        return checkInDetailVo;
    }

    /**
     * 查询入住列表
     * 
     * @param checkIn 入住
     * @return 入住
     */
    @Override
    public List<CheckIn> selectCheckInList(CheckIn checkIn)
    {
        return checkInMapper.selectCheckInList(checkIn);
    }

    /**
     * 新增入住
     * 
     * @param checkIn 入住
     * @return 结果
     */
    @Override
    public int insertCheckIn(CheckIn checkIn)
    {
        return checkInMapper.insert(checkIn);
    }

    /**
     * 修改入住
     * 
     * @param checkIn 入住
     * @return 结果
     */
    @Override
    public int updateCheckIn(CheckIn checkIn)
    {
        return checkInMapper.updateById(checkIn);
    }

    /**
     * 批量删除入住
     * 
     * @param ids 需要删除的入住主键
     * @return 结果
     */
    @Override
    public int deleteCheckInByIds(Long[] ids)
    {
        return checkInMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除入住信息
     * 
     * @param id 入住主键
     * @return 结果
     */
    @Override
    public int deleteCheckInById(Long id)
    {
        return checkInMapper.deleteById(id);
    }
}
